import socket
from PyQt5.QtWidgets import (QMainWindow, QWidget, QPushButton,
                             QVBoxLayout, QHBoxLayout, QSpacerItem,
                             QSizePolicy, QMessageBox, QLabel)
from PyQt5.QtCore import Qt, QTimer
from .widgets.log_viewer import LogViewer
from .widgets.qr_dialog import QRDialog
from .widgets.port_scan_dialog import PortScanDialog
from queue import Empty
from core.web_server import run_server, log_queue, notification_queue, server_status
from core.port_scanner import PortScanner
from core.monitor import Monitor
from core.audio_player import AudioPlayer


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("监控应用程序")
        self.setGeometry(100, 100, 1000, 700)
        self.server_process = None
        self.log_viewer = LogViewer()  # 先创建 log_viewer
        self.process_log_queue = None
        self.process_notification_queue = None
        self.monitor = Monitor(None, self.log_viewer_callback)  # 初始时不传递队列
        self.audio_player = AudioPlayer()  # 创建音频播放器实例

        # 创建音频状态检查定时器
        self.audio_status_timer = QTimer()
        self.audio_status_timer.timeout.connect(self.update_audio_status)
        self.audio_status_timer.start(1000)  # 每秒更新一次

        # 创建通知检查定时器
        self.notification_timer = QTimer()
        self.notification_timer.timeout.connect(self.check_notifications)
        self.notification_timer.start(100)  # 每0.1秒检查一次

        self.init_ui()

        # 延迟一小段时间后自动检测端口和启动服务
        QTimer.singleShot(500, self.auto_start_service)

    def init_ui(self):
        # 创建中央部件和主布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # 创建按钮区域
        button_widget = QWidget()
        button_layout = QHBoxLayout(button_widget)

        # 创建按钮
        buttons = {
            'port_scan': '端口检测',
            'check_notifications': '声音检测',
            'service_control': '启动服务',  # 合并的启动/停止按钮
            'stop_sound': '停止声音',
            'connect_mobile': '手机连接',
            'exit': '退出'
        }

        self.buttons = {}
        for key, text in buttons.items():
            btn = QPushButton(text)
            btn.setMinimumWidth(100)
            self.buttons[key] = btn
            button_layout.addWidget(btn)

        # 添加弹性空间，使按钮均匀分布
        button_layout.addStretch()

        # 设置按钮点击事件
        self.buttons['exit'].clicked.connect(self.on_exit)
        self.buttons['port_scan'].clicked.connect(self.on_port_scan)
        self.buttons['service_control'].clicked.connect(
            self.on_service_control)
        self.buttons['check_notifications'].clicked.connect(
            self.on_check_notifications)
        self.buttons['stop_sound'].clicked.connect(self.on_stop_sound)
        self.buttons['connect_mobile'].clicked.connect(self.on_connect_mobile)

        # 设置控制按钮的初始状态
        self.service_is_running = False

        # 设置按钮样式
        self.style_buttons()

        # 添加按钮区域到主布局
        main_layout.addWidget(button_widget)

        # 创建状态标签容器
        status_widget = QWidget()
        status_layout = QHBoxLayout(status_widget)
        status_layout.setContentsMargins(5, 5, 5, 5)  # 设置边距

        # 创建服务状态标签
        self.status_label = QLabel("服务状态: 未启动")
        self.status_label.setStyleSheet("""
            QLabel {
                color: #666666;
                padding: 8px 15px;
                border-radius: 4px;
                background-color: #f2dede;
                font-size: 14px;
                font-weight: bold;
            }
        """)
        self.status_label.setAlignment(Qt.AlignCenter)  # 文字居中对齐
        status_layout.addWidget(self.status_label)

        # 添加状态标签区域到主布局
        main_layout.addWidget(status_widget)

        # 更新状态显示
        self.update_service_button_state()

        # 设置日志查看器
        self.log_viewer = LogViewer()
        main_layout.addWidget(self.log_viewer)

    def style_buttons(self):
        """设置按钮样式"""
        base_style = """
            QPushButton {
                padding: 8px;
                border-radius: 4px;
                background-color: #2b579a;
                color: white;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #3b67aa;
            }
            QPushButton:pressed {
                background-color: #1b4789;
            }
        """

        for btn in self.buttons.values():
            btn.setStyleSheet(base_style)

    def on_port_scan(self):
        """检测端口5000的状态"""
        self.log_viewer.append_log("正在检测端口5000...")
        try:
            scanner = PortScanner()
            port_info = scanner.check_port_5000()

            dialog = PortScanDialog(self, port_info, scanner)
            self.log_viewer.append_log(
                "端口空闲" if port_info['status'] == 'free'
                else "端口被占用"
            )
            dialog.exec_()

        except Exception as e:
            self.log_viewer.append_log(f"端口检测失败: {str(e)}")
            QMessageBox.warning(
                self,
                "错误",
                f"端口检测过程中发生错误：{str(e)}"
            )

    def log_viewer_callback(self, message):
        """接收监控消息并显示在日志查看器中"""
        self.log_viewer.append_log(message)

    def update_service_button_state(self):
        """更新服务控制按钮的状态和文字"""
        button = self.buttons['service_control']
        if self.service_is_running:
            button.setText('停止服务')
            button.setStyleSheet("""
                QPushButton {
                    background-color: #d9534f;
                    color: white;
                    padding: 8px;
                    border-radius: 4px;
                    font-size: 14px;
                }
                QPushButton:hover {
                    background-color: #c9302c;
                }
                QPushButton:pressed {
                    background-color: #ac2925;
                }
            """)
            self.status_label.setText("服务状态: 运行中")
            self.status_label.setStyleSheet("""
                QLabel {
                    color: #3c763d;
                    padding: 8px 15px;
                    border-radius: 4px;
                    background-color: #dff0d8;
                    font-size: 14px;
                    font-weight: bold;
                }
            """)
        else:
            button.setText('启动服务')
            self.style_buttons()  # 恢复默认样式
            self.status_label.setText("服务状态: 已停止")
            self.status_label.setStyleSheet("""
                QLabel {
                    color: #666666;
                    padding: 8px 15px;
                    border-radius: 4px;
                    background-color: #f2dede;
                    font-size: 14px;
                    font-weight: bold;
                }
            """)

    def start_service(self):
        """启动服务"""
        try:
            # 更新服务状态
            server_status['is_running'] = True

            # 启动 Flask 服务，传递队列给子进程
            import multiprocessing
            # 确保在 Windows 下使用 spawn 方式创建进程
            if multiprocessing.get_start_method() != 'spawn':
                multiprocessing.set_start_method('spawn', force=True)

            # 创建新的队列实例
            self.process_log_queue = multiprocessing.Queue()
            self.process_notification_queue = multiprocessing.Queue()

            # 启动服务并传递队列
            self.server_process = multiprocessing.Process(
                target=run_server,
                args=(self.process_log_queue, self.process_notification_queue)
            )
            self.server_process.daemon = True

            # 在启动之前确保进程不存在
            if hasattr(self, 'server_process') and self.server_process and self.server_process.is_alive():
                self.server_process.terminate()
                self.server_process.join(timeout=3)

            self.server_process.start()

            # 更新监视器使用的队列
            self.monitor.stop()  # 确保先停止旧的监视器
            self.monitor = Monitor(
                self.process_log_queue, self.log_viewer_callback)
            self.monitor.start()

            self.log_viewer.append_log("Flask 服务已启动在 http://localhost:5000")
            self.log_viewer.append_log("API 接口已就绪：")
            self.log_viewer.append_log("  - GET/POST /api/notifications")
            self.log_viewer.append_log("  - GET /api/status")
            self.log_viewer.append_log("  - GET /api/messages")
            self.log_viewer.append_log("监控服务已启动")

            self.service_is_running = True
            self.update_service_button_state()
            return True
        except Exception as e:
            server_status['is_running'] = False
            self.log_viewer.append_log(f"启动服务失败: {str(e)}")
            return False

    def stop_service(self):
        """停止服务"""
        if self.server_process and self.server_process.is_alive():
            try:
                # 停止监控服务
                self.monitor.stop()

                # 停止 Web 服务
                self.server_process.terminate()
                self.server_process.join(timeout=3)
                if self.server_process.is_alive():
                    self.server_process.kill()
                self.server_process = None

                self.service_is_running = False
                self.update_service_button_state()
                return True
            except Exception as e:
                self.log_viewer.append_log(f"停止服务时发生错误: {str(e)}")
                return False
        return True

    def on_service_control(self):
        """处理服务控制按钮点击事件"""
        if not self.service_is_running:
            if self.server_process and self.server_process.is_alive():
                self.log_viewer.append_log("服务已经在运行中...")
                return

            self.log_viewer.append_log("正在启动服务...")
            if self.start_service():
                self.log_viewer.append_log("服务启动成功")
            else:
                self.log_viewer.append_log("服务启动失败")
        else:
            self.log_viewer.append_log("正在停止服务...")
            if self.stop_service():
                self.log_viewer.append_log("服务已停止")
            else:
                self.log_viewer.append_log("停止服务失败")

    def on_check_notifications(self):
        """检查通知并播放提示音"""
        self.log_viewer.append_log("正在检查通知...")

        # 检查系统音量
        if self.audio_player.is_system_muted():
            QMessageBox.warning(
                self,
                "系统音量提示",
                "系统当前处于静音状态，您可能听不到提示音。\n请检查系统音量设置。"
            )
            self.log_viewer.append_log("警告：系统当前处于静音状态")
            return

        # 尝试播放提示音
        try:
            result = self.audio_player.play_sound()
            if result == "MUTED":
                self.log_viewer.append_log("警告：系统音量为0，无法播放提示音")
            elif result:
                self.log_viewer.append_log("正在播放提示音...")
            else:
                self.log_viewer.append_log("提示音正在播放中，请等待当前播放完成")
        except FileNotFoundError as e:
            self.log_viewer.append_log(f"播放提示音失败: {str(e)}")

    def on_stop_sound(self):
        """停止声音播放"""
        if self.audio_player.stop_sound():
            self.log_viewer.append_log("已停止声音提醒")
        else:
            self.log_viewer.append_log("当前没有正在播放的声音")

    def get_local_ip(self):
        """获取局域网IP地址"""
        try:
            # 创建一个临时socket连接来获取局域网IP
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            # 不实际连接，只是用来获取当前网络接口的IP
            s.connect(('8.8.8.8', 80))
            local_ip = s.getsockname()[0]
            s.close()
            return local_ip
        except Exception as e:
            # 发生异常时使用localhost作为备选
            self.log_viewer.append_log(f"获取局域网IP失败: {str(e)}")
            return "localhost"

    def on_connect_mobile(self):
        """显示手机连接二维码对话框"""
        # 获取局域网IP地址
        local_ip = self.get_local_ip()
        # 构建可通过手机访问的URL
        connection_url = f"http://{local_ip}:5000/mobile-connect"

        self.log_viewer.append_log(f"生成手机连接URL: {connection_url}")

        dialog = QRDialog(self, connection_url)
        self.log_viewer.append_log("已打开手机连接二维码")
        dialog.exec_()
        dialog.deleteLater()

    def closeEvent(self, event):
        """重写关闭事件，确保在应用程序关闭前停止所有服务"""
        self.log_viewer.append_log("正在关闭应用程序...")
        if self.service_is_running:
            self.log_viewer.append_log("正在停止运行中的服务...")
            if not self.stop_service():
                self.log_viewer.append_log("警告：无法正常停止服务")
        event.accept()

    def update_audio_status(self):
        """更新音频播放状态"""
        if self.audio_player.is_playing:
            self.buttons['stop_sound'].setEnabled(True)
            self.buttons['check_notifications'].setEnabled(False)
        else:
            self.buttons['stop_sound'].setEnabled(False)
            self.buttons['check_notifications'].setEnabled(True)

    def check_notifications(self):
        """检查通知队列并处理新通知"""
        try:
            if self.process_notification_queue:  # 确保队列已初始化
                while True:  # 持续检查直到队列为空
                    try:
                        notification = self.process_notification_queue.get_nowait()
                        if notification['type'] == 'notification':
                            self.log_viewer.append_log("收到新通知，准备处理...")
                            self.handle_new_notification(notification['data'])
                    except Empty:
                        break  # 队列为空时退出循环
        except Exception as e:
            self.log_viewer.append_log(f"处理通知时出错: {str(e)}")
            import traceback
            self.log_viewer.append_log(traceback.format_exc())

    def handle_new_notification(self, notification_data):
        """处理新的通知"""
        try:
            # 添加通知到日志
            message = f"收到新通知 [{notification_data.get('timestamp', '未知时间')}]"
            if 'title' in notification_data:
                message += f"\n标题: {notification_data['title']}"
            if 'message' in notification_data:
                message += f"\n内容: {notification_data['message']}"

            self.log_viewer.append_log(message)

            # 播放提示音
            self.play_notification_sound()

            # 激活窗口并置顶
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.show()  # 需要重新显示窗口以应用新的窗口标志

            # 如果窗口被最小化，则恢复窗口
            if self.isMinimized():
                self.showNormal()

            self.raise_()  # 将窗口提升到最前面
            self.activateWindow()  # 激活窗口

            # 显示系统通知（对话框会自动置顶）
            dialog = QMessageBox(
                QMessageBox.Information,
                "新通知",
                message,
                QMessageBox.Ok,
                self
            )
            # 设置对话框置顶
            dialog.setWindowFlags(dialog.windowFlags() |
                                  Qt.WindowStaysOnTopHint)
            dialog.exec_()

            # 处理完通知后恢复窗口正常状态
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.show()  # 重新显示窗口以应用更新的窗口标志
        except Exception as e:
            self.log_viewer.append_log(f"处理通知详情时出错: {str(e)}")

    def play_notification_sound(self):
        """播放通知提示音"""
        try:
            # 检查系统音量
            if self.audio_player.is_system_muted():
                self.log_viewer.append_log("警告：系统当前处于静音状态")
                QMessageBox.warning(
                    self,
                    "系统音量提示",
                    "系统当前处于静音状态，您可能听不到提示音。\n请检查系统音量设置。"
                )
                return

            # 播放提示音
            result = self.audio_player.play_sound()
            if result == "MUTED":
                self.log_viewer.append_log("警告：系统音量为0，无法播放提示音")
            elif not result:
                self.log_viewer.append_log("提示音正在播放中，跳过本次播放")
        except Exception as e:
            self.log_viewer.append_log(f"播放提示音时出错: {str(e)}")

    def auto_start_service(self):
        """自动检测端口并启动服务"""
        self.log_viewer.append_log("正在进行启动前检查...")

        try:
            # 1. 检查端口
            self.log_viewer.append_log("正在检测端口5000状态...")
            scanner = PortScanner()
            port_info = scanner.check_port_5000()

            if port_info['status'] == 'free':
                self.log_viewer.append_log("端口5000空闲，可以启动服务")

                # 2. 尝试启动服务
                self.log_viewer.append_log("正在启动服务...")
                if self.start_service():
                    self.log_viewer.append_log("服务启动成功！")
                    self.log_viewer.append_log("监控服务已就绪，等待接收通知...")
                else:
                    self.log_viewer.append_log("服务启动失败，请检查日志了解详细信息")
            else:
                self.log_viewer.append_log(
                    f"警告：端口5000被占用（进程：{port_info.get('process_name', '未知')}）")
                QMessageBox.warning(
                    self,
                    "端口占用提示",
                    f"端口5000已被其他程序占用！\n占用进程：{port_info.get('process_name', '未知')}\n"
                    "请关闭占用端口的程序后再试。"
                )
        except Exception as e:
            self.log_viewer.append_log(f"自动启动过程中发生错误: {str(e)}")
            QMessageBox.critical(
                self,
                "启动错误",
                f"启动过程中发生错误：\n{str(e)}"
            )

    def on_exit(self):
        """处理退出按钮点击事件"""
        self.close()
